import { _decorator, BoxCollider2D, Camera, Collider2D, Component, director, EPhysics2DDrawFlags, EventKeyboard, EventTouch, find, geometry, input, Input, instantiate, Intersection2D, JsonAsset, KeyCode, Label, Node, PhysicsSystem, PhysicsSystem2D, PolygonCollider2D, Prefab, Rect, Sprite, SpriteFrame, tween, UIOpacity, UITransform, v2, v3, Vec2, Vec3, Widget } from 'cc';
import { LayerRootAction } from './game/LayerRootAction';
import { Global } from './game/Global';
import { LayerCatAction } from './game/LayerCatAction';
import { LayerEmptyAction } from './game/LayerEmptyAction';
import { TipsAction } from './game/TipsAction';
import { BucketAction } from './game/BucketAction';
import { events } from './game/Enums';
import { CatAction } from './game/CatAction';
import { Tools } from './game/Tools';

import { PinAction } from './game/PinAction';
import { ElementAction } from './game/ElementAction';
import { gameRevival } from './game/gameRevival';
import { GameOver } from './game/GameOver';
import { FishMgr } from './game/fish/FishMgr';

const { ccclass, property } = _decorator;

@ccclass('gameMgr')
export class gameMgr extends Component {

    @property({ type: LayerRootAction })
    layer_root: LayerRootAction
    @property({ type: LayerCatAction })
    layer_cat: LayerCatAction
    @property({ type: LayerEmptyAction })
    layer_empty: LayerEmptyAction
    // @property({type:ShowLevelAction})
    // Show_level_action:ShowLevelAction

    // @property({type:MenuAction})
    // menu:MenuAction
    // @property({type:GameOverAction})
    // game_over_action:GameOverAction
    // @property({type:CoinsAction})
    // coins_action:CoinsAction
    // @property({type:SuccessAction})
    // success_action:SuccessAction
    // @property({type:LayerBtnAction})
    // layer_btn_action:LayerBtnAction
    @property({ type: TipsAction })
    tips_action: TipsAction;

    @property({ type: BucketAction })
    bucket_action: BucketAction;

    @property(Node)
    game_revive: Node = null;

    @property({ type: [SpriteFrame] })
    dcImgs: SpriteFrame[] = [];

    @property({ type: [SpriteFrame] })
    boxImgs: SpriteFrame[] = [];

    @property({ type: [SpriteFrame] })
    paoImgs: SpriteFrame[] = [];

    @property({ type: [SpriteFrame] })
    zdImgs: SpriteFrame[] = [];

    // @property({type:PropsAction})
    // props_action:PropsAction;

    @property(Node)
    game_success: Node = null;

    @property(Node)
    game_over: Node = null;


    @property(Sprite)
    coin_spr: Sprite = null;

    @property(Label)
    progress_lab: Label = null;

    @property({ type: Node })
    layer_down_node: Node;

    //进度
    cur_progress = 0;


    @property(JsonAsset)
    game_json: JsonAsset = null;

    @property(JsonAsset)
    layer_json: JsonAsset = null;
    
    canvasNode: Node = null;

    _camera: Camera = null;

    //是否可点击板子(道具用)
    is_click_board = false;
    //是否可点击电池
    is_click_battery = true;

    static Inst: gameMgr = null;

    onLoad() {
        gameMgr.Inst = this;

        //PhysicsSystem2D.instance.enable = true;

        Global.dcImgs = this.dcImgs;
        Global.boxImgs = this.boxImgs;
        Global.paoImgs = this.paoImgs;
        Global.zdImgs = this.zdImgs;

        //检查游戏是否完成
        director.on(events.check_completed, this.on_game_continue, this);
        director.on(events.game_over, this.on_game_over, this);

        this.canvasNode = find('Canvas');

        this._camera = find("Canvas/Camera").getComponent(Camera);

        this.node.on(Input.EventType.TOUCH_START, this.on_click_collider, this);

        this.is_click_board = false;
        this.is_click_battery = true;

        //7.3
        this.node.on(Input.EventType.TOUCH_START, this.on_click_battery, this);
        // this.scheduleOnce(() => {
        //     director.emit(events.remove_board, false);
        // }, 0.5)



        //监听按键
        input.on(Input.EventType.KEY_DOWN, this.onKeyDown, this);
    }

    async start() {
        // PhysicsSystem2D.instance.debugDrawFlags =
        //     EPhysics2DDrawFlags.Shape //| EPhysics2DDrawFlags.Joint;

        Global.layer_root_action = this.layer_root;
        Global.layer_cat_action = this.layer_cat;
        Global.layer_empty_action = this.layer_empty;
        Global.main_action = this;
        //    Global.Show_level_action = this.Show_level_action;
        //    Global.game_over_action = this.game_over_action;
        //    Global.coins_action = this.coins_action;
        //    Global.success_action = this.success_action;
        //    Global.layer_btn_action = this.layer_btn_action;
        Global.tips_action = this.tips_action;
        Global.bucket_action = this.bucket_action;
        Global.game_revive = this.game_revive.getComponent(gameRevival)
        //    Global.props_action = this.props_action; 


        // this.layer_root.init_root(1);

        //console.log("json: " , this.game_json.json)

        if (Global.cur_lvl_index >= this.game_json.json.length) return;

        const _data = this.game_json.json[Global.cur_lvl_index];

        await this.layer_root.init_root_read_config(_data);

        let bat_data = this.get_battery_color_data(_data)
        let bat_c_data = this.get_bat_cang_color_data(bat_data.slice())

        //注： 电池颜色数据需要反转 ， 电池仓不需要；因为cocos层级的问题，新添加的节点在外层，所以需要反转数据
        this.layer_root.init_color_data(bat_data.reverse(), bat_c_data);

        //测试
        // this.scheduleOnce(()=>{
        //     this.on_click_collider_pos(v2(498.333 , 398.333));
        // },1)
    }

    /** 电池颜色数据 */
    get_battery_color_data(json: any) {
        let layer = []
        let color_data: number[] = []//存入索引

        console.log("layer json :", this.layer_json);

        //根据关卡 获取layer
        for (let i = 0; i < json.layer.length; i++) {
            const lay_id = json.layer[i] - 1; //因为是索引 需要减一
            const layer_data = this.layer_json.json[lay_id].colorNum;
            layer.push(layer_data);
        }
        console.log("layer :", layer);

        //每层数据 存入数组
        for (let j = 0; j < layer.length; j++) {
            const _colors = layer[j];

            let temp_lay: new_index_val[] = [];

            for (let k = 0; k < _colors.length; k++) {
                let _newIndexVal: new_index_val = new_index_val.new(k, _colors[k])
                //color_lays.push(_newIndexVal);
                temp_lay.push(_newIndexVal)
            }

            let temp_data: number[] = []

            for (let k = 0; k < temp_lay.length; k++) {
                const _c_lay_val = temp_lay[k].val;
                temp_data = temp_data.concat(new Array(_c_lay_val).fill(temp_lay[k].index))
            }

            //打乱每层数据
            temp_data.sort(() => {
                return 0.5 - Math.random();
            });

            color_data = color_data.concat(temp_data);
        }

        console.log("配置表原始颜色数据(索引数组)：", color_data);

        return color_data
    }

    /** 电池仓数据 --->改 25.7.9.18.11 */
    get_bat_cang_color_data(bat_data: number[]) {

        let bat_cang_data: number[] = []

        let track = bat_data[0];
        const _length = bat_data.length
        for (let i = 0; i < _length; i++) {

            bat_cang_data.push(track)
            //移除三次
            let index = bat_data.indexOf(track);
            if (index != -1) bat_data.splice(index, 1);
            index = bat_data.indexOf(track);
            if (index != -1) bat_data.splice(index, 1);
            index = bat_data.indexOf(track);
            if (index != -1) bat_data.splice(index, 1);

            if (bat_data.length > 0)
                track = bat_data[0];
            else
                break;
        }

        return bat_cang_data;
    }


    /** 检查是否过关,游戏继续 */
    on_game_continue(catAction: CatAction) {
        console.log("继续")
        // Global.success_action.open();return;

        const cur_num = Global.cur_lvl_pin_total - Global.cur_lvl_pin_move_num;

        this.scheduleOnce(() => this.add_coin_anim(cur_num), 1.5)

        if (cur_num <= 0) {
            // console.log(" check is completed  success");
            // Global.success_action.open();
            console.log("过关")

        } else {
            LayerCatAction.Inst.layer_pinNum();
            
            catAction.into_scence();
        }
    }

    add_coin_anim(cur_num: number) {
        const progress = 1 - cur_num / Global.cur_lvl_pin_total;
        tween(this.coin_spr).to(0.7, { fillRange: progress }).start();

        const _val = Math.floor(progress * 100);
        const obj = { val: this.cur_progress };
        let pregressTw = tween(obj).to(0.7, { val: _val }, {
            onUpdate: () => {
                let _z_val = Math.floor(obj.val);

                //写这个 if 是因为 重新开始游戏时，此动画没结束 this.progress_lab 会 = null 报错
                if (!this.progress_lab) {
                    pregressTw.stop();
                    return;
                }
                this.progress_lab.string = (_z_val + '%');
            }
        }).call(() => {
            //进度100 弹窗过关界面
            if (this.cur_progress >= 100) {
                this.scheduleOnce(() => {
                    //隐藏所有鱼
                    FishMgr.Inst.hideFishs();
                })

                this.scheduleOnce(() => {
                    Tools.updateWidget(this.game_success);
                }, 1.2)//钱袋进度到达100% 弹出 过关界面
            }
        }).start();

        this.cur_progress = _val;
    }

    /** 复活 */
    onRevive() {
        console.log("gameMgr onReveive")

        this.on_add_hole();
    }

    /** 游戏结束 */
    on_game_over() {
        console.log("游戏结束")
        this.game_over.setPosition(v3(0, 0, 0))

        this.game_over.getComponent(GameOver).game_over(this.cur_progress);
    }

    on_restart_game() {
        director.emit(events.objpool_pin, this);
        director.loadScene('game')
    }

    /** 下一关 */
    on_next_game() {
        Global.cur_lvl_index++;
        director.loadScene('game')
    }

    /** 返回首页 */
    on_goto_Home() {
        director.emit(events.objpool_pin, this);
        director.loadScene('home')
    }

    /** 增加孔 */
    on_add_hole() {
        console.log("加孔")

        this.layer_empty.add_empty_hole();
    }

    /** 清除电池 */
    on_clear_battery() {
        console.log("清除电池");

        let pin_arr = this.layer_empty.get_pin_arr();
        if (pin_arr.length == 0) {
            console.log("没有可清除的电池");
            return;
        }
        this.bucket_action.put_pins(pin_arr);
    }

    /** 移除板子 (按钮) */
    on_remove_board() {
        this.is_click_board = true;
    }

    /** 点击板子碰撞器 */
    on_click_collider(e: EventTouch) {
        if (!this.is_click_board) return;

        let _pos = e.getUILocation();
        console.log("点击", _pos)

        this.on_click_collider_pos(_pos)
    }

    on_click_collider_pos(_pos: Vec2) {

        // 执行射线检测
        const collider = PhysicsSystem2D.instance.testPoint(_pos);

        //console.log(collider)

        let cur_node: Node = null;

        if (collider.length > 0) {
            let n_index = -1;

            let _sindex = -1;
            for (let i = 0; i < collider.length; i++) {
                const n = collider[i].node;
                if (!n.getComponent(ElementAction)) {
                    continue;
                }

                //只判断板子

                let sindex = n.parent.getSiblingIndex();

                if (n_index == -1) n_index = i;

                if (sindex > _sindex) {
                    _sindex = sindex;
                    n_index = i;
                }

                console.log(n.name)
            }

            if (n_index != -1)
                cur_node = collider[n_index].node;
        }

        //最外层的板子
        if (cur_node) {
            console.log('点击板子，消除', cur_node.name)
            cur_node.active = false;

            let pin_arr: PinAction[] = [];
            cur_node.getComponent(ElementAction).get_pin_color(pin_arr);
            console.log(pin_arr.length);

            let pin_arr_out: PinAction[] = [];
            //清除板子的电池 
            pin_arr.forEach((pin, index) => {
                let b = Global.layer_cat_action.put_pin(pin);
                console.log(index, b)
                if (!b) {
                    pin_arr_out.push(pin)
                }
            });
            console.log(pin_arr_out)
            this.bucket_action.put_pins(pin_arr_out);



            this.scheduleOnce(() => {
                this.is_click_board = false;

                //先移除，再更新板子
                cur_node.removeFromParent();
                director.emit(events.update_element, cur_node);
            })

        }
        else {
            console.log('点击板子 null')

        }
    }


    //7.3
    /** 点击电池碰撞器 */
    on_click_battery(e: EventTouch) {
        //不可点击电池 or 可点击板子时 返回
        if (!this.is_click_battery || this.is_click_board) return;

        let _pos = e.getUILocation();

        this.on_test_pos(_pos);
    }
    on_test_pos(_pos: Vec2) {

        // 执行射线检测
        let collider = PhysicsSystem2D.instance.testPoint(_pos).slice();


        console.log(_pos, "--->碰撞器：", collider)

        let cur_node: Node = null;

        if (collider.length <= 0) return

        let n_index = -1;

        let ele_or_hole_cols: Collider2D[] = [];


        //索引 点击的电池 layer 层级 越大越上面
        let _sindex = -1;
        for (let i = 0; i < collider.length; i++) {
            const n = collider[i].node;
            if (n.name != "battery_img") {
                if (n.name != "battery")
                    ele_or_hole_cols.push(collider[i])//板子碰撞器 和 洞的碰撞器

                continue;
            }

            if (n.name != "battery_img") {
                console.warn("不是battery_img")
            }

            if (n_index == -1) n_index = i;

            let sindex = n.parent.parent.parent.getSiblingIndex();
            //console.log("名字：", n.parent.parent.parent.name, sindex, n_index, i)
            if (sindex > _sindex) {
                _sindex = sindex;
                n_index = i;
            }
        }

        //console.log(n_index)

        if (n_index != -1)
            cur_node = collider[n_index].node;


        //点击到电池
        if (cur_node) {
            //console.log('点击', cur_node.name)

            let isGgg = true;
            for (let i = 0; i < cur_node.children.length; i++) {
                const _child = cur_node.children[i];
                let worldPos = _child.getComponent(UITransform).convertToWorldSpaceAR(Vec3.ZERO)
                //边界 子节点射线检测
                if(!this.on_test_pos_child(cur_node , _sindex , Tools.V3ToV2(worldPos))){
                    isGgg = false;
                }
            }

            if(isGgg){
                console.log("全部通过")
                cur_node.parent.getComponent(PinAction).touch_start(null);
            }
            

            return
        }
        else {
            console.log('点击 null')

        }
    }
    //电池碰撞器下面的子节点判定边界
    on_test_pos_child(cur_node: Node, _sindex: number , _pos: Vec2) {

        let collider = PhysicsSystem2D.instance.testPoint(_pos).slice();

        //console.log(collider)

        if (collider.length <= 0) return true;

        let ele_or_hole_cols: Collider2D[] = [];
        let battery_cols: Collider2D[] = [];


        for (let i = 0; i < collider.length; i++) {
            const n = collider[i].node;
            if (n.name != "battery_img" && n.name != "battery") {
                    ele_or_hole_cols.push(collider[i])//板子碰撞器 和 洞的碰撞器

                continue;
            }

            //console.log("名字：", n.name)
            if (n.name != "battery_img") {
                console.warn("不是battery_img")
            }

            if (n.name == "battery_img")
                battery_cols.push(collider[i])

        }

        //检测此电池

        let isCan = true;

        //板子遮挡
        for (let i = ele_or_hole_cols.length - 1; i >= 0; i--) {
            const ele = ele_or_hole_cols[i];
            let sibindex = ele.node.parent.getSiblingIndex()

            //是否被孔洞挡住(不需要了)
            //if (ele.node.name == Global.hole_node_name) sibindex = ele.node.parent.parent.getSiblingIndex()

            //是否被上层碰撞器遮挡
            if (_sindex < sibindex) {
                isCan = false;
                //break;
                    //console.log("板子遮挡 不通过",ele.node.name , ele.node.parent.name , cur_node.parent.parent.name , _sindex , sibindex)
            }
            else {
                ele_or_hole_cols.splice(i, 1);
            }
        }
        //电池遮挡   ps:不用算电池遮挡
        // for (let i = battery_cols.length - 1; i >= 0; i--) {
        //     const ele = battery_cols[i];
        //     let sibindex = ele.node.parent.parent.parent.getSiblingIndex()
        //     //是否被上层碰撞器遮挡
        //     if (_sindex < sibindex && ele.node != cur_node) {
        //         isCan = false;
        //         //break;
        //         //console.log("电池遮挡 不通过",ele.node.name)
        //     }
        //     else {
        //         battery_cols.splice(i, 1);
        //     }
        // }

        //console.log(isCan, " cols ：", ele_or_hole_cols)


        return isCan
    }




    /** 关闭窗口 */
    on_close_page(date: string) {
        switch (date) {
            case 'tips':
                find("Canvas/game_tips").setPosition(v3(1800, 0, 0));
                break;
            case '':

                break;
            case '':

                break;
            default:
                break;
        }
    }


    onKeyDown(event: EventKeyboard) {
        let code = event.keyCode
        switch (code) {
            case KeyCode.ARROW_RIGHT:
                console.log('右箭头按键被按下');
                Global.cur_lvl_index++;
                this.on_restart_game();
                break;
        }
    }
}



class new_index_val {
    index: number;
    val: number;

    public static new(i: number, v: number) {
        let ret = new new_index_val();
        ret.index = i;
        ret.val = v;
        return ret;
    }

    public clone(): new_index_val {
        return new_index_val.new(this.index, this.val);
    }

}